home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / net / netamsrc.arc / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-02-12  |  15.2 KB  |  730 lines

  1. /* Main network program - provides both client and server functions */
  2.  
  3. #define HOSTNAMELEN 32        /* changed from 16 by Bdale 860812 */
  4.  
  5. extern char startup[];    /* File to read startup commands from */
  6.  
  7. #include <stdio.h>
  8. #include "global.h"
  9. #include "config.h"
  10. #include "mbuf.h"
  11. #include "netuser.h"
  12. #include "timer.h"
  13. #include "icmp.h"
  14. #include "iface.h"
  15. #include "ip.h"
  16. #include "tcp.h"
  17. #include "ax25.h"
  18. #include "ftp.h"
  19. #include "telnet.h"
  20. #include "session.h"
  21. #include "cmdparse.h"
  22.  
  23. #ifdef UNIX        /* BSD or SYS5 */
  24. #include "unix.h"
  25. #endif
  26.  
  27. #ifdef AMIGA
  28. #include "amiga.h"
  29. #endif
  30.  
  31. #ifdef MAC
  32. #include "mac.h"
  33. #endif
  34.  
  35. #ifdef MSDOS
  36. #include "pc.h"
  37. #endif
  38.  
  39. #ifdef    TRACE
  40. #include "trace.h"
  41. /* Dummy structure for loopback tracing */
  42. struct interface loopback = { NULLIF, "loopback" };
  43. #endif
  44.  
  45. extern struct interface *ifaces;
  46. extern char version[];
  47. extern struct mbuf *loopq;
  48.  
  49. int mode;
  50. FILE *logfp;
  51. char badhost[] = "Unknown host %s\n";
  52. char hostname[HOSTNAMELEN];    
  53. unsigned nsessions = NSESSIONS;
  54. int32 resolve();
  55. int16 lport = 1001;
  56. char prompt[] = "net> ";
  57. char nospace[] = "No space!!\n";    /* Generic malloc fail message */
  58.  
  59.  
  60. #ifndef    MSDOS            /* PC uses F-10 key always */
  61. static char escape = 0x1d;    /* default escape character is ^] */
  62. #endif
  63.  
  64. /* Command lookup and branch table */
  65. int go(),doax25(),cmdmode(),doconnect(),dotelnet(),doexit(),doclose(),
  66.     dohostname(),doreset(),dotcp(),dotrace(),doescape(),dohelp(),
  67.     doroute(),doecho(),dolog(),doip(),doetherstat(),
  68.     memstat(),doarp(),dosession(),doftp(),dostart(),dostop(),doattach(),
  69.     dosmtp(),doudp(),doparam(),doeol(),dohapnstat(),
  70.     doegstat(),dodump(),dorecord(),doupload(),dokick(),domode(),doshell(),
  71.     dodir(),docd(),doatstat(),doping();
  72.  
  73. static struct cmds cmds[] = {
  74.     /* The "go" command must be first */
  75.     "",        go,        0, NULLCHAR,    NULLCHAR,
  76.     "!",        doshell,    0, NULLCHAR,    NULLCHAR,
  77. #if    (defined(MAC) && defined(APPLETALK))
  78.     "applestat",    doatstat,    0,    NULLCHAR,    NULLCHAR,
  79. #endif
  80. #if    (defined(AX25) || defined(ETHER) || defined(APPLETALK))
  81.     "arp",        doarp,        0, NULLCHAR,    NULLCHAR,
  82. #endif
  83. #ifdef    AX25
  84.     "ax25",        doax25,        0, NULLCHAR,    NULLCHAR,
  85. #endif    
  86.     "attach",    doattach,    2,
  87.         "attach <hardware> <hw specific options>", NULLCHAR,
  88. /* This one is out of alpabetical order to allow abbreviation to "c" */
  89. #ifdef    AX25
  90.     "connect",    doconnect,    3,"connect interface callsign [digipeaters]",
  91.         NULLCHAR,
  92. #endif
  93. #ifndef UNIX    /* BSD or SYS5 */
  94.     "cd",        docd,        0, NULLCHAR,    NULLCHAR,
  95. #endif
  96.     "close",    doclose,    0, NULLCHAR,    NULLCHAR,
  97.     "disconnect",    doclose,    0, NULLCHAR,    NULLCHAR,
  98.     "dir",        dodir,        0, NULLCHAR,    NULLCHAR,
  99. #ifdef    EAGLE
  100.     "eaglestat",    doegstat,    0, NULLCHAR,    NULLCHAR,
  101. #endif
  102.     "echo",        doecho,        0, NULLCHAR,    "echo [refuse|accept]",
  103.     "eol",        doeol,        0, NULLCHAR,
  104.         "eol options: unix, standard",
  105. #ifndef    MSDOS
  106.     "escape",    doescape,    0, NULLCHAR,    NULLCHAR,   
  107. #endif
  108. #ifdef    PC_EC
  109.     "etherstat",    doetherstat,    0, NULLCHAR,    NULLCHAR,
  110. #endif  PC_EC
  111.     "exit",        doexit,        0, NULLCHAR,    NULLCHAR,
  112.     "ftp",        doftp,        2, "ftp <address>",    NULLCHAR,
  113. #ifdef HAPN
  114.     "hapnstat",    dohapnstat,    0, NULLCHAR,    NULLCHAR,
  115. #endif HAPN
  116.     "help",        dohelp,        0, NULLCHAR,    NULLCHAR,
  117.     "hostname",    dohostname,    0, NULLCHAR,    NULLCHAR,
  118.     "kick",        dokick,        0, NULLCHAR,    NULLCHAR,
  119.     "log",        dolog,        0, NULLCHAR,    NULLCHAR,
  120.     "ip",        doip,        0, NULLCHAR,    NULLCHAR,
  121.     "memstat",    memstat,    0, NULLCHAR,    NULLCHAR,
  122. #ifdef    AX25
  123.     "mode",        domode,        2, "mode <interface>",    NULLCHAR,
  124. #endif
  125.     "param",    doparam,    2, "param <interface>", NULLCHAR,
  126.     "ping",        doping,        0, NULLCHAR,    NULLCHAR,
  127. #ifndef UNIX /* BSD or SYS5 */
  128.     "pwd",        docd,        0, NULLCHAR,    NULLCHAR,
  129. #endif
  130.     "record",    dorecord,    0, NULLCHAR,    NULLCHAR,
  131.     "reset",    doreset,    0, NULLCHAR,    NULLCHAR,
  132.     "route",    doroute,    0, NULLCHAR,    NULLCHAR,
  133.     "session",    dosession,    0, NULLCHAR,    NULLCHAR,
  134.     "shell",    doshell,    0, NULLCHAR,    NULLCHAR,
  135.     "smtp",        dosmtp,        0, NULLCHAR,    NULLCHAR,
  136. #ifdef    SERVERS
  137.     "start",    dostart,    2, "start <servername>",NULLCHAR,
  138.     "stop",        dostop,        2, "stop <servername>",    NULLCHAR,
  139. #endif
  140.     "tcp",        dotcp,        0, NULLCHAR,    NULLCHAR,
  141.     "telnet",    dotelnet,    2, "telnet <address>",    NULLCHAR,
  142. #ifdef    TRACE
  143.     "trace",    dotrace,    0, NULLCHAR,    NULLCHAR,
  144. #endif
  145.     "udp",        doudp,        0, NULLCHAR,    NULLCHAR,
  146.     "upload",    doupload,    0, NULLCHAR,    NULLCHAR,
  147.     "?",        dohelp,        0, NULLCHAR,    NULLCHAR,
  148.     NULLCHAR,    NULLFP,        0,
  149.         "Unknown command; type \"?\" for list",   NULLCHAR, 
  150. };
  151.  
  152. #ifdef    SERVERS
  153. /* "start" and "stop" subcommands */
  154. int ftp_start(),smtp_start(),discard_start(),echo_start(),telnet_start();
  155. int tnc_start();
  156. static struct cmds startcmds[] = {
  157.     "discard",    discard_start,    0, NULLCHAR, NULLCHAR,
  158.     "echo",        echo_start,    0, NULLCHAR, NULLCHAR,
  159.     "ftp",        ftp_start,    0, NULLCHAR, NULLCHAR,
  160.     "smtp",        smtp_start,    0, NULLCHAR, NULLCHAR,
  161.     "telnet",    telnet_start,    0, NULLCHAR, NULLCHAR,
  162.     NULLCHAR,    NULLFP,        0,
  163.         "start options: discard, echo, ftp, smtp, telnet", NULLCHAR,
  164. };
  165. int ftp_stop(),smtp_stop(),echo_stop(),discard_stop(),telnet_stop();
  166. static struct cmds stopcmds[] = {
  167.     "discard",    discard_stop,    0, NULLCHAR, NULLCHAR,
  168.     "echo",        echo_stop,    0, NULLCHAR, NULLCHAR,
  169.     "ftp",        ftp_stop,    0, NULLCHAR, NULLCHAR,
  170.     "smtp",        smtp_stop,    0, NULLCHAR, NULLCHAR,
  171.     "telnet",    telnet_stop,    0, NULLCHAR, NULLCHAR,
  172.     NULLCHAR,    NULLFP,        0,
  173.         "stop options: discard, echo, ftp, smtp, telnet",  NULLCHAR,
  174. };
  175. #endif
  176.  
  177. main(argc,argv)
  178. int argc;
  179. char *argv[];
  180. {
  181.     static char inbuf[BUFSIZ];    /* keep it off the stack */
  182.     int c;
  183.     char *ttybuf,*fgets();
  184.     int16 cnt;
  185.     int ttydriv();
  186.     int cmdparse();
  187.     void check_time();
  188.     FILE *fp;
  189.     struct interface *ifp;
  190.     struct mbuf *bp;
  191.  
  192.     ioinit();
  193. #if    (defined(UNIX) || defined(AMIGA) || defined(MAC))
  194. #else
  195.     chktasker();
  196. #endif
  197. #ifdef    MSDOS
  198.     printf("KA9Q Internet Protocol Package, v%s DS = %x\n",version,
  199.         getds());
  200. #else
  201.     printf("KA9Q Internet Protocol Package, v%s\n",version);
  202. #endif
  203.     printf("Copyright 1988 by Phil Karn, KA9Q\n");
  204.     sessions = (struct session *)calloc(nsessions,sizeof(struct session));
  205.     if(argc > 1){
  206.         /* Read startup file named on command line */
  207.         fp = fopen(argv[1],"r");
  208.     } else {
  209.         fp = fopen(startup,"r");
  210.     }
  211.     if(fp != NULLFILE){
  212.         while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
  213.             cmdparse(cmds,inbuf);
  214.         }
  215.         fclose(fp);
  216.     }        
  217.     cmdmode();
  218.  
  219.     /* Main commutator loop */
  220.     for(;;){
  221.         /* Process any keyboard input */
  222.         while((c = kbread()) != -1){
  223. #ifdef    MSDOS
  224.             /* c == -2 means the command escape key (F10) */
  225.             if(c == -2){
  226.                 if(mode != CMD_MODE){
  227.                     printf("\n");
  228.                     cmdmode();
  229.                 }
  230.                 continue;
  231.             }
  232. #endif
  233. #ifdef SYS5
  234.             if(c == escape && escape != 0){
  235.                 if(mode != CMD_MODE){
  236.                     printf("\r\n");
  237.                     cmdmode();
  238.                 }
  239.                 continue;
  240.             }
  241. #endif     /* SYS5 */
  242.             if((cnt = ttydriv(c,&ttybuf)) == 0)
  243.                 continue;
  244.             switch(mode){
  245.             case CMD_MODE:
  246.                 (void)cmdparse(cmds,ttybuf);
  247.                 fflush(stdout);
  248.                 break;
  249.             case CONV_MODE:
  250. #ifndef    MSDOS
  251.                 if(ttybuf[0] == escape && escape != 0){
  252.                     printf("\n");
  253.                     cmdmode();
  254.                 } else
  255. #endif MSDOS
  256.                     if(current->parse != NULLFP)
  257.                         (*current->parse)(ttybuf,cnt);
  258.  
  259.                 break;
  260.             }
  261.             if(mode == CMD_MODE){
  262.                 printf(prompt);
  263.                 fflush(stdout);
  264.             }
  265.         }
  266.         /* Service the loopback queue */
  267.         while((bp = dequeue(&loopq)) != NULLBUF){
  268.             struct ip ip;
  269. #ifdef    TRACE
  270.             dump(&loopback,IF_TRACE_IN,TRACE_IP,bp);        
  271. #endif
  272.             /* Extract IP header */
  273.             ntohip(&ip,&bp);
  274.             ip_recv(&ip,bp,0);
  275.         }
  276.         /* Service the interfaces */
  277.         for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next){
  278.             if(ifp->recv != NULLFP)
  279.                 (*ifp->recv)(ifp);
  280.         }
  281.  
  282.         /* Service the clock if it has ticked */
  283.         check_time();
  284.  
  285. #ifdef    MSDOS
  286.         /* Tell DoubleDos to let the other task run for awhile.
  287.          * If DoubleDos isn't active, this is a no-op
  288.          */
  289.         giveup();
  290. #else
  291.         /* Wait until interrupt, then do it all over again */
  292.         eihalt();
  293. #endif
  294.     }
  295. }
  296. /* Standard commands called from main */
  297.  
  298. /* Enter command mode */
  299. int
  300. cmdmode()
  301. {
  302.     if(mode != CMD_MODE){
  303.         mode = CMD_MODE;
  304.         cooked();
  305.         printf(prompt);
  306.         fflush(stdout);
  307.     }
  308.     return 0;
  309. }
  310. static
  311. doexit(argc,argv)
  312. int argc;
  313. char *argv[];
  314. {
  315.     if(logfp != NULLFILE)
  316.         fclose(logfp);
  317.     iostop();
  318.     exit(0);
  319. }
  320. static
  321. dohostname(argc,argv)
  322. int argc;
  323. char *argv[];
  324. {
  325.     char *strncpy();
  326.  
  327.     if(argc < 2)
  328.         printf("%s\n",hostname);
  329.     else 
  330.         strncpy(hostname,argv[1],HOSTNAMELEN);
  331.     return 0;
  332. }
  333. static
  334. int
  335. dolog(argc,argv)
  336. int argc;
  337. char *argv[];
  338. {
  339.     char *strncpy();
  340.  
  341.     static char logname[15];
  342.     if(argc < 2){
  343.         if(logfp)
  344.             printf("Logging to %s\n",logname);
  345.         else
  346.             printf("Logging off\n");
  347.         return 0;
  348.     }
  349.     if(logfp){
  350.         fclose(logfp);
  351.         logfp = NULLFILE;
  352.     }
  353.     if(strcmp(argv[1],"stop") != 0){
  354.         strncpy(logname,argv[1],15);
  355.         logfp = fopen(logname,"a+");
  356.     }
  357.     return 0;
  358. }
  359. static
  360. int
  361. dohelp(argc,argv)
  362. int argc;
  363. char *argv[];
  364. {
  365.     register struct cmds *cmdp;
  366.     int i,j;
  367.  
  368.     printf("Main commands:\n");
  369.     for(i=0,cmdp = cmds;cmdp->name != NULL;cmdp++,i++){
  370.         printf("%s",cmdp->name);
  371.         if((i % 4) == 3)
  372.             printf("\n");
  373.         else {
  374.             for(j=strlen(cmdp->name);j < 16; j++)
  375.                 putchar(' ');
  376.         }
  377.     }
  378.     if((i % 4) != 0)
  379.         printf("\n");
  380.     return 0;
  381. }
  382.  
  383. doecho(argc,argv)
  384. int argc;
  385. char *argv[];
  386. {
  387.     extern int refuse_echo;
  388.  
  389.     if(argc < 2){
  390.         if(refuse_echo)
  391.             printf("Refuse\n");
  392.         else
  393.             printf("Accept\n");
  394.     } else {
  395.         if(argv[1][0] == 'r')
  396.             refuse_echo = 1;
  397.         else if(argv[1][0] == 'a')
  398.             refuse_echo = 0;
  399.         else
  400.             return -1;
  401.     }
  402.     return 0;
  403. }
  404. /* set for unix end of line for remote echo mode telnet */
  405. doeol(argc,argv)
  406. int argc;
  407. char *argv[];
  408. {
  409.     extern int unix_line_mode;
  410.  
  411.     if(argc < 2){
  412.         if(unix_line_mode)
  413.             printf("Unix\n");
  414.         else
  415.             printf("Standard\n");
  416.     } else {
  417.         if(strcmp(argv[1],"unix") == 0)
  418.             unix_line_mode = 1;
  419.         else if(strcmp(argv[1],"standard") == 0)
  420.             unix_line_mode = 0;
  421.         else {
  422.             return -1;
  423.         }
  424.     }
  425.     return 0;
  426. }
  427. /* Attach an interface
  428.  * Syntax: attach <hw type> <I/O address> <vector> <mode> <label> <bufsize> [<speed>]
  429.  */
  430. doattach(argc,argv)
  431. int argc;
  432. char *argv[];
  433. {
  434.     extern struct cmds attab[];
  435.  
  436.     return subcmd(attab,argc,argv);
  437. }
  438. /* Manipulate I/O device parameters */
  439. doparam(argc,argv)
  440. int argc;
  441. char *argv[];
  442. {
  443.     register struct interface *ifp;
  444.  
  445.     for(ifp=ifaces;ifp != NULLIF;ifp = ifp->next){
  446.         if(strcmp(argv[1],ifp->name) == 0)
  447.             break;
  448.     }
  449.     if(ifp == NULLIF){
  450.         printf("Interface \"%s\" unknown\n",argv[1]);
  451.         return 1;
  452.     }
  453.     if(ifp->ioctl == NULLFP){
  454.         printf("Not supported\n");
  455.         return 1;
  456.     }
  457.     /* Pass rest of args to device-specific code */
  458.     return (*ifp->ioctl)(ifp,argc-2,argv+2);
  459. }
  460. /* Log messages of the form
  461.  * Tue Jan 31 00:00:00 1987 44.64.0.7:1003 open FTP
  462.  */
  463. /*VARARGS2*/
  464. log(tcb,fmt,arg1,arg2,arg3,arg4)
  465. struct tcb *tcb;
  466. char *fmt;
  467. int arg1,arg2,arg3,arg4;
  468. {
  469.     char *cp;
  470.     long t;
  471.     int fd;
  472.  
  473.     if(logfp == NULLFILE)
  474.         return;
  475.     time(&t);
  476.     cp = ctime(&t);
  477.     rip(cp);
  478.     fprintf(logfp,"%s %s - ",cp,psocket(&tcb->conn.remote));
  479.     fprintf(logfp,fmt,arg1,arg2,arg3,arg4);
  480.     fprintf(logfp,"\n");
  481.     fflush(logfp);
  482. #ifdef    MSDOS
  483.     /* MS-DOS doesn't really flush files until they're closed */
  484.     fd = fileno(logfp);
  485.     if((fd = dup(fd)) != -1)
  486.         close(fd);
  487. #endif
  488. }
  489. /* Configuration-dependent code */
  490.  
  491. /* List of supported hardware devices */
  492. int ec_attach(),asy_attach(),pc_attach(),eg_attach(),hapn_attach(),at_attach();
  493.  
  494. struct cmds attab[] = {
  495. #ifdef    PC_EC
  496.     /* 3-Com Ethernet interface */
  497.     "3c500", ec_attach, 7, 
  498.     "attach 3c500 <address> <vector> arpa <label> <buffers> <mtu>",
  499.     "Could not attach 3c500",
  500. #endif
  501. #ifdef    SLIP
  502.     /* Ordinary PC asynchronous adaptor */
  503.     "asy", asy_attach, 8, 
  504.     "attach asy <address> <vector> slip|ax25 <label> <buffers> <mtu> <speed>",
  505.     "Could not attach asy",
  506. #endif
  507. #ifdef    PC100
  508.     /* PACCOMM PC-100 8530 HDLC adaptor */
  509.     "pc100", pc_attach, 8, 
  510.     "attach pc100 <address> <vector> ax25 <label> <buffers> <mtu> <speed>",
  511.     "Could not attach pc100",
  512. #endif
  513. #ifdef    EAGLE
  514.     /* EAGLE RS-232C 8530 HDLC adaptor */
  515.     "eagle", eg_attach, 8,
  516.     "attach eagle <address> <vector> ax25 <label> <buffers> <mtu> <speed>",
  517.     "Could not attach eagle",
  518. #endif
  519. #ifdef    HAPN
  520.     /* Hamilton Area Packet Radio (HAPN) 8273 HDLC adaptor */
  521.     "hapn", hapn_attach, 8,
  522.     "attach hapn <address> <vector> ax25 <label> <rx bufsize> <mtu> csma|full",
  523.     "Could not attach hapn",
  524. #endif
  525. #ifdef    APPLETALK
  526.     /* Macintosh AppleTalk */
  527.     "appletalk", at_attach, 7,
  528.     "attach appletalk <protocol type> <device> arpa <label> <rx bufsize> <mtu>",
  529.     "Could not attach Appletalk",
  530. #endif
  531.     NULLCHAR, NULLFP, 0,
  532.     "Unknown device",
  533.     NULLCHAR,
  534. };
  535.  
  536. /* Protocol tracing function pointers */
  537. #ifdef    TRACE
  538. int ax25_dump(),ether_dump(),ip_dump(),at_dump();
  539.  
  540. int (*tracef[])() = {
  541. #ifdef    AX25
  542.     ax25_dump,
  543. #else
  544.     NULLFP,
  545. #endif
  546.  
  547. #ifdef    ETHER
  548.     ether_dump,
  549. #else
  550.     NULLFP,
  551. #endif
  552.     ip_dump,
  553.  
  554. #ifdef    APPLETALK
  555.     at_dump,
  556. #else
  557.     NULLFP,
  558. #endif
  559. };
  560. #else
  561. int (*tracef[])() = { NULLFP };    /* No tracing at all */
  562. dump(interface,direction,type,bp)
  563. struct interface *interface;
  564. int direction;
  565. unsigned type;
  566. struct mbuf *bp;
  567. {
  568. }
  569. #endif
  570.  
  571. #ifdef    AX25
  572. /* Set up a SLIP link to use AX.25 */
  573. kiss_attach(if_asy,srecv)
  574. struct interface *if_asy;
  575. int (**srecv)();
  576. {
  577.     int kiss_ioctl(),ax_send(),ax_output(),kiss_raw(),kiss_recv();
  578.  
  579.     axarp();
  580.     if(mycall.call[0] == '\0'){
  581.         printf("set mycall first\n");
  582.         free((char *)if_asy);
  583.         return -1;
  584.     }
  585.     if_asy->ioctl = kiss_ioctl;
  586.     if_asy->send = ax_send;
  587.     if_asy->output = ax_output;
  588.     if_asy->raw = kiss_raw;
  589.     if(if_asy->hwaddr == NULLCHAR)
  590.         if_asy->hwaddr = malloc(sizeof(mycall));
  591.     memcpy(if_asy->hwaddr,(char *)&mycall,sizeof(mycall));
  592.     *srecv = kiss_recv;
  593.     return 0;
  594. }
  595. /* Display or set IP interface control flags */
  596. domode(argc,argv)
  597. int argc;
  598. char *argv[];
  599. {
  600.     register struct interface *ifp;
  601.  
  602.     for(ifp=ifaces;ifp != NULLIF;ifp = ifp->next){
  603.         if(strcmp(argv[1],ifp->name) == 0)
  604.             break;
  605.     }
  606.     if(ifp == NULLIF){
  607.         printf("Interface \"%s\" unknown\n",argv[1]);
  608.         return 1;
  609.     }
  610.     if(argc < 3){
  611.         printf("%s: %s\n",ifp->name,
  612.          (ifp->flags & CONNECT_MODE) ? "VC mode" : "Datagram mode");
  613.         return 0;
  614.     }
  615.     switch(argv[2][0]){
  616.     case 'v':
  617.     case 'c':
  618.     case 'V':
  619.     case 'C':
  620.         ifp->flags = CONNECT_MODE;
  621.         break;
  622.     case 'd':
  623.     case 'D':
  624.         ifp->flags = DATAGRAM_MODE;
  625.         break;
  626.     default:
  627.         printf("Usage: %s [vc | datagram]\n",argv[0]);
  628.         return 1;
  629.     }
  630.     return 0;
  631. }
  632. #else    /* KISS mode not configured */
  633. kiss_attach(if_asy,srecv)
  634. struct interface *if_asy;
  635. int (*srecv)();
  636. {
  637.     printf("KISS mode not configured\n");
  638.     return -1;
  639. }
  640. #endif
  641.  
  642. #ifdef SERVERS
  643. dostart(argc,argv)
  644. int argc;
  645. char *argv[];
  646. {
  647.     return subcmd(startcmds,argc,argv);
  648. }
  649. dostop(argc,argv)
  650. int argc;
  651. char *argv[];
  652. {
  653.     return subcmd(stopcmds,argc,argv);
  654. }
  655. #endif SERVERS
  656.  
  657. #ifdef    TRACE
  658. static
  659. int
  660. dotrace(argc,argv)
  661. int argc;
  662. char *argv[];
  663. {
  664.     struct interface *ifp;
  665.  
  666.     if(argc < 2){
  667.         showtrace(&loopback);
  668.         for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
  669.             showtrace(ifp);
  670.         return 0;
  671.     }
  672.     if(strcmp("loopback",argv[1]) == 0)
  673.         ifp = &loopback;
  674.     else 
  675.         for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
  676.             if(strcmp(ifp->name,argv[1]) == 0)
  677.                 break;
  678.  
  679.     if(ifp == NULLIF){
  680.         printf("Interface %s unknown\n",argv[1]);
  681.         return 1;
  682.     }
  683.     if(argc >= 3)
  684.         ifp->trace = htoi(argv[2]);
  685.  
  686.     showtrace(ifp);
  687.     return 0;
  688. }
  689. /* Display the trace flags for a particular interface */
  690. static
  691. showtrace(ifp)
  692. register struct interface *ifp;
  693. {
  694.     if(ifp == NULLIF)
  695.         return;
  696.     printf("%s:",ifp->name);
  697.     if(ifp->trace & (IF_TRACE_IN | IF_TRACE_OUT)){
  698.         if(ifp->trace & IF_TRACE_IN)
  699.             printf(" input");
  700.         if(ifp->trace & IF_TRACE_OUT)
  701.             printf(" output");
  702.  
  703.         if(ifp->trace & IF_TRACE_HEX)
  704.             printf(" (Hex/ASCII dump)");
  705.         else if(ifp->trace & IF_TRACE_ASCII)
  706.             printf(" (ASCII dump)");
  707.         else
  708.             printf(" (headers only)");
  709.         printf("\n");
  710.     } else
  711.         printf(" tracing off\n");
  712.     fflush(stdout);
  713. }
  714. #endif
  715.  
  716. #ifndef    MSDOS
  717. static
  718. int
  719. doescape(argc,argv)
  720. int argc;
  721. char *argv[];
  722. {
  723.     if(argc < 2)
  724.         printf("0x%x\n",escape);
  725.     else 
  726.         escape = *argv[1];
  727.     return 0;
  728. }
  729. #endif    MSDOS
  730.